package com.baizhi.aop;

import com.baizhi.entity.Emp;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import redis.clients.jedis.JedisCluster;

import java.util.List;
import java.util.Map;

//注解用于标识或者描述AOP中的切面类型，基于切面类型构建的对象用于为目标对象进行功能扩展或控制目标对象的执行。
@Aspect
//将对象交给spring容器管理
@Component
@Slf4j
public class CacheAOP {
    //公式: AOP = 切入点表达式 + 通知方法

    @Autowired
    private JedisCluster jedis;

    @Around("@annotation(cacheFind)")
    public Object around(ProceedingJoinPoint jp, CacheFind cacheFind) throws Throwable{
        log.info("AOP开始方法执行:"+System.currentTimeMillis());
        Object result=null;
        //1.获取key
        String key = cacheFind.key();
        //获取目标方法中的参数
        for(int i=0;i<jp.getArgs().length;i++){
            if(jp.getArgs()[i]!=null && jp.getArgs()[i]!=""){
                key = key+"_"+(String)jp.getArgs()[i].toString();
            }
        }
        log.info("通过注解获取的键:"+key);
       if(jedis.exists(key)){
            log.info("AOP查询Redis缓存获取换回的结果");
            //从缓存中获取数据
            String json = jedis.get(key);
            //获取方法返回值类型的对象
            MethodSignature methodSignature = (MethodSignature)jp.getSignature();
            //将json转对象
            result = ObjectMapperUtil.toObject(json, methodSignature.getReturnType());

            Map<String,Object> map=(Map<String, Object>) result;
            List<Emp> li= (List<Emp>)map.get("emps");
            log.info("Redis缓存获取的总行数:"+map.get("rowCount"));
            log.info("Redis缓存获取总页数:"+map.get("pageCount"));
            log.info("遍历Redis缓存获取的结果如下");


       }else {
           try {
               log.info("AOP查询数据库获取返回值结果");
               //执行目标方法,并返回结果
               result = jp.proceed();

               Map<String,Object> map=(Map<String, Object>) result;
               List<Emp> li= (List<Emp>)map.get("emps");
               log.info("AOP查询数据库获取的总行数:"+map.get("rowCount"));
               log.info("AOP查询数据库获取总页数:"+map.get("pageCount"));
               log.info("遍历AOP获取的结果如下:");


               //将emps对象转json
               String json = ObjectMapperUtil.toJson(result);
               //将json存到redis中
               if (cacheFind.secondes() > 0) {//判断是否需要给缓存设置生命周期
                   jedis.setex(key, cacheFind.secondes(), json);
               } else {
                   jedis.set(key, json);
               }
           } catch (Throwable e) {
               e.printStackTrace();
               throw new RuntimeException(e);
           }
       }
       log.info("AOP执行完毕:"+System.currentTimeMillis());
       return result;
    }

}
